package com.CircleSingleLinkedList;

public class CircleSingleLinkedList {
    //还未添加结点时，先创建一个First结点
    private Node first = null;

    /**
     * 添加结点构建环形链表
     *
     * @param nums 添加结点个数
     */
    public void addNode(int nums) {
        //nums有效性校验
        if (nums < 1) {
            System.out.println("nums的值不正确");
            return;
        }
        Node curNode = null;
        //使用for循环创建环形链表
        for (int i = 1; i <= nums; i++) {
            //根据编号创建结点
            Node node = new Node(i);
            //如果是第一个结点，则将first指向头结点，并和自己构成环状
            if (i == 1) {
                first = node;
                first.setNext(first);
                //辅助变量也指向第一个结点
                curNode = first;
            }
            //curNode表示原本链表的最后一个结点
            //新加入结点时将curNode指向新结点，新结点next指向头结点first构成环状
            //之后移动curNode结点指向新结点
            curNode.setNext(node);
            node.setNext(first);
            curNode = node;
        }
    }

    /*
    遍历环形链表，创建辅助变量curNode指向头结点，通过curNode进行遍历，直至curNode.next == first
     */
    public void showNode() {
        //判断链表时候为空
        if (first == null) {
            System.out.println("链表中没有结点");
            return;
        }
        //因为first不能动，所以需要辅助指针进行遍历
        Node curNode = first;
        while (true) {
            System.out.println("结点编号为:" + curNode.getNo());
            if (curNode.getNext() == first) {
                //遍历到最后一个结点
                break;
            }
            curNode = curNode.getNext();
        }
    }


    /*
    思路分析：根据指定数字移除出圈
    first指向头结点，辅助结点helper指向first结点后一个结点
    数数时则通过循环将first和helper移动m-1个位置，此时first指向的结点即出圈的结点
    first = first.next
    helper.next = first
    即将出圈结点从环形链表中移除
     */

    /**
     * 根据用户输入指定位置按照指定数字依次输出结点，输出以后删除该结点
     *
     * @param startNo  从第几号结点开始数
     * @param countNum 数几下
     * @param nums     最初链表中有多少个结点
     */
    public void showByOrder(int startNo, int countNum, int nums) {
        //数据校验
        if (first == null || startNo < 1 || startNo > nums) {
            System.out.println("参数输入有误，请重新输入");
            return;
        }
        //创建辅助变量helper循环指向first后一个结点
        Node helper = first;
        while (helper.getNext() != first) {
            helper = helper.getNext();
        }
        //从第startNo开始报数，先移动startNo-1次
        for (int i = 0; i < startNo - 1; i++) {
            first = first.getNext();
            helper = helper.getNext();
        }
        while (nums != 0) {
            //开始数数,循环m-1次
            for (int i = 0; i < countNum - 1; i++) {
                first = first.getNext();
                helper = helper.getNext();
            }
            //结点出队
            System.out.println("出队结点编号为：" + first.getNo());
            first = first.getNext();
            helper.setNext(first);
            nums--;
        }
    }
}
